In [1]:
from IPython.display import Image
from IPython.core.display import HTML 
Image(url= "https://img.techpowerup.org/201119/logo147.png", width=900, height=300)
Out[1]:

Abbreviations: \ GMP : Green Mountain Power ( distributor) \ PRO : Prosumer

Mathematical Fomulation

Assumptions

  • All parameters are deterministic and given in the beginning
  • The same charge/discharge limitation and efficiency rates are used for battery and EV.
  • In GMP's model, Real-Time Locational Marginal Price (LMP) (\$/kWh) in Vermont is used. The buying and selling prices are equal.
  • In prosumer's model, three tarrif schemes are used; \begin{cases} rate 1 & \text{(flat)} & \text{Customer Charge = } & \$0.492/day, & \text{Usage = } & \$0.16859/kWh\\ rate 11 & \text{(Time-of-Use)} & \text{Customer Charge = } & \$0.651/day, & \text{Usage/Peak = } & \$0.26771/kWh\\ & & & & \text{Usage/Off-Peak = } & \$0.11411/kWh\\ rate 74 & \text{(Time-of-Use for EV)} & \text{Customer Charge = } & \$0.492/day, & \text{General usage = } & \$0.16859/kWh\\ & & & & \text{EV Usage/Peak = } & \$0.16859/kWh\\ & & & & \text{EV Usage/Off-Peak = } & \$0.12831/kWh\\ \end{cases}
  • More details on the rates is avaiable on : https://greenmountainpower.com/rates/
  • Prosumer buys electricity at one of the above listed rates and, if trade is allowed ($I^{trade} = 1$), s/he sells at rates 1 or 11.

Indexes

\begin{align*} t \in& \{\mathcal{T}\} & \text{ episode } t \text{ in horizon } [1,2,3,...,T] \\ k \in& \{\mathcal{K}\} & \text{ month } k \text{ in horizon } [1,2,3,...,K] \end{align*}
  • 15 minutes time-step (t) is considered here. Note that when 1 kWh is used during this time interval means that 4 kW of power/capacity are being used.

Parameters

\begin{align*} B^{max} =& \text{ capacity (kWh) of battery} &=& \quad \{0, 10, 27, 40.5\}\\ B^{min} =& \text{ minimum allowed electricity (kWh) in battery} &=& \quad 0\\ E^{max} =& \text{ capacity (kWh) of EV} &=& \quad 60\\ E^{min} =& \text{ minimum allowed electricity (kWh) in EV} &=& \quad 24\\ U^c =& \text{ charging capacity (kWh) of battery/EV during the interval} &=& \quad \{0, 1.9, 2.5, 3.75\}\\ U^d =& \text{ discharging capacity (kWh) of battery/EV during the interval} &=& \quad \{0, 1.9, 2.5, 3.75\}\\ 1-\eta^c =& \text{ charging loss rate} &=& \quad 0.05\\ 1-\eta^d =& \text{ discharging loss rate} &=& \quad 0.05\\ P^{rns} =& \text{ cost coefficient (\$/kW) of RNS} &=& \quad 9\\ P^{cap} =& \text{ cost coefficient (\$/kW) of capacity} &=& \quad 5\\ P^{buy}_t =& \text{ electricity price (\$/kWh) to buy from grid at time } t \\ P^{sell}_t =& \text{ electricity price (\$/kWh) to sell to grid at time } t \\ L_{t} =& \text{ load (kWh) at time } t\\ A_t =& \text{ availability of EV at time } t \text{ under the chosen scenario }\\ V_t =& \text{ EV usage (kWh) (for vehicle riding) at time } t \text{ under the chosen scenario }\\ R_{t} =& \text{ electricity generation (kWh) from solar panel } t\\ I^{trade} =& \text{ indicates if it is allowed to sell electricity to grid }\\ \end{align*}

Decision Variables

\begin{align*} x^{GL}_{t} =& \text{ electricity (kWh) from grid to load at time } t\\ x^{GB}_{t} =& \text{ electricity (kWh) from grid to battery at time } t\\ x^{GE}_{t} =& \text{ electricity (kWh) from grid to EV at time } t\\ x^{RL}_{t} =& \text{ electricity (kWh) from solar panel to load at time } t\\ x^{RB}_{t} =& \text{ electricity (kWh) from solar panel to battery at time } t\\ x^{RE}_{t} =& \text{ electricity (kWh) from solar panel to EV at time } t\\ x^{RG}_{t} =& \text{ electricity (kWh) from solar panel to grid at time } t\\ x^{BL}_{t} =& \text{ electricity (kWh) from battery to load at time } t\\ x^{EL}_{t} =& \text{ electricity (kWh) from EV to load at time } t\\ x^{BG}_{t} =& \text{ electricity (kWh) from battery to grid at time } t\\ x^{EG}_{t} =& \text{ electricity (kWh) from EV to grid at time } t\\ x^{peak}_{k} =& \text{ maximum electricity (kWh) taken from grid in an episode in month } k\\ \end{align*}

The decision variables' set then is defined as : $X_t \doteq \{ x^{RL}_{t}, x^{RB}_{t}, x^{RE}_{t}, x^{RG}_{t}, x^{BG}_{t}, x^{EG}_{t}, x^{BL}_{t}, x^{EL}_{t}, x^{GL}_{t}, x^{GB}_{t}, x^{GE}_{t}, x^{peak}_{k}\}$

State Variables

\begin{align*} b_t^B =& \text{ state of the battery (available electricity (kWh) in battery) at time } t \\ b_t^E =& \text{ state of the EV (available electricity (kWh) in battery) at time } t \end{align*}

Distributor's Model

\begin{equation} \min \sum_{t=1}^T \big( P^{buy}_t (x^{GL}_t + x^{GB}_t + x^{GE}_t) - P^{sell}_t ( x^{RG}_t + \eta^d x^{BG}_t + \eta^d x^{EG}_t ) \big) + 4 \sum_{k=1}^{12} (P^{rns} + 1.35 P^{cap}) x_{k}^{peak} \label{obj_2} \tag{1} \end{equation}

s.t. \begin{align} x^{GL}_t + \eta^d (x^{BL}_t + x^{EL}_t) + x^{RL}_t \geq& L_t & \forall t \label{c_load_2} \tag{2}\\ x^{BL}_t + x^{BG}_t \leq& b_t^B & \forall t \label{c_bat_state_2} \tag{3}\\ x^{EL}_t + x^{EG}_t \leq& b_t^E A_t & \forall t \label{c_ev_state_2} \tag{4}\\ x^{GE}_t + x^{RE}_t \leq& E^{max} A_t & \forall t \label{c_ev_2_state_2} \tag{5}\\ x^{BL}_t + x^{EL}_t + x^{BG}_t + x^{EG}_t \leq& U^d & \forall t \label{c_dch_max_2} \tag{6}\\ x^{GB}_t + x^{GE}_t + x^{RB}_t + x^{RE}_t \leq& U^c & \forall t \label{c_ch_max_2} \tag{7}\\ B^{min} \leq b_t^B \leq& B^{max} & \forall t \label{c_b_bat_max_2} \tag{8}\\ E^{min} \leq b_t^E \leq& E^{max} & \forall t \label{c_b_ev_max_2} \tag{9}\\ x^{RL}_t + x^{RB}_t + x^{RE}_t + x^{RG}_t \leq& R_t & \forall t \label{c_gen_cap_2} \tag{10}\\ b_t^B + \eta^c (x^{GB}_t + x^{RB}_t) - ( x^{BL}_t + x^{BG}_t) =& b_{t+1}^B & \forall t \label{c_bat_next_state_2} \tag{11}\\ b_t^E + \eta^c (x^{GE}_t + x^{RE}_t) - ( x^{EL}_t + x^{EG}_t) - \frac{V_t}{\eta^d} =& b_{t+1}^E & \forall t \label{c_ev_next_state_2} \tag{12}\\ x^{GL}_{t} + x^{GB}_{t} + x^{GE}_{t} \leq& x_{k}^{peak} & \forall t \in k, k\label{c_max_2} \tag{13}\\ x^{RL}_{t}, x^{RB}_{t}, x^{RE}_{t}, x^{RG}_{t}, x^{BG}_{t}, x^{EG}_{t}, x^{BL}_{t}, x^{EL}_{t}, x^{GL}_{t}, x^{GB}_{t}, x^{GE}_{t}, x^{peak}_{k}, b_t^B, b_t^E \geq& 0 & \forall t \label{c_domain_2} \tag{14} \end{align}

Objective function \ref{obj_2} minimizes electricity consumption cost. Constraint \ref{c_load_2} makes sure load is covered. Constraints \ref{c_bat_state_2} to \ref{c_ev_2_state_2} state that electricity taken out of battery or EV must be firstly less than the available energy stored in them and secondly, electricity can be taken from or sent to EV, when it is available. Constraints \ref{c_dch_max_2} and \ref{c_ch_max_2} indicate the charging and discharging limits. Constraints \ref{c_b_bat_max_2} and \ref{c_b_ev_max_2} make sure the state of battery and EV are in the allowed range of stored energy in them. Constraint \ref{c_gen_cap_2} checks electricity sent from solar panel would be less than or equal to the generated electricity and constraints \ref{c_bat_next_state_2} and \ref{c_ev_next_state_2} calculate the state of battery and EV in the next episode. Constraint \ref{c_max_2} calculates the maximum electricity taken from grid in month $k$. Finally, constraint \ref{c_domain_2} specifies the domain of the decision variables.

Prosumer's model

\begin{equation} \min \sum_{t=1}^T \big( P^{buy}_t (x^{GL}_t + x^{GB}_t + x^{GE}_t) - P^{sell}_t ( x^{RG}_t + \eta^d x^{BG}_t + \eta^d x^{EG}_t ) \big) \label{obj_3} \tag{15} \end{equation}

s.t. constraints 2 t0 12 and \begin{align} x^{RG}_t + x^{BG}_t + x^{EG}_t \leq& (U^d + R_t) I^{trade} & \forall t\label{c_max_3} \tag{16}\\ x^{RL}_{t}, x^{RB}_{t}, x^{RE}_{t}, x^{RG}_{t}, x^{BG}_{t}, x^{EG}_{t}, x^{BL}_{t}, x^{EL}_{t}, x^{GL}_{t}, x^{GB}_{t}, x^{GE}_{t}, b_t^B, b_t^E \geq& 0 & \forall t \label{c_domain_3} \tag{17} \end{align}

Objective function \ref{obj_3} minimizes electricity consumption cost. Constraint \ref{c_max_3} makes sure the prosumer can sell electricity to grid if trade is allowed and, constraint \ref{c_domain_3} specifies the domain of the decision variables.

Costs

  • capacity cost is multiplied by 1.35, to account for the required capacity margin above the peak use
  • In the figures/tables the below terms are used and are defined as follows: \begin{align*} &\text{Default cost of load covering } :=&& P^{buy}_t L_t \\ &\text{Cost of load covering by agent } :=&& P^{buy}_t (x^{GL}_t + x^{GB}_t + x^{GE}_t) - P^{sell}_t ( x^{RG}_t + \eta^d x^{BG}_t + \eta^d x^{EG}_t )\\ &\text{Capacity cost } :=&& 4 (P^{rns} + 1.35 P^{cap}) x_{k}^{peak} \\ \end{align*}

NPV and Internal Rate of Return (IRR) formulas

\begin{align*} NPV =& \sum_{n=1}^{N} \{\frac{\text{Yearly Saving}}{ (1+i)^N}\} - (\text{Product price+ Installation and Labor cost}) \\ 0 =& \sum_{n=1}^{N} \{\frac{\text{Yearly Saving}}{ (1+IRR)^N}\} - (\text{Product price+ Installation and Labor cost}) \\ \text{Yearly Saving} = & \text{Total Cost - Base Cost} + \text{EV Usage Cost}\\ i =& \text{ Discount rate } &=& \quad 0.0619 \\ N =& \text{ Life time of the product(s) } &=& \quad 15 \end{align*}

scenarios

\begin{cases} \text{s0 : } &\text{B_max: 0,} &\text{B_min: 0,} &\text{U_c: 0,} &\text{U_d: 0,} &\text{E_max: 0,} &\text{E_min: 0,} &\text{use_pv: False,} &\text{price: 0,}\\ \text{s1 : } &\text{B_max: 40.5,} &\text{B_min: 0,} &\text{U_c: 3.75,} &\text{U_d: 3.75,} &\text{E_max: 0,} &\text{E_min: 0,} &\text{use_pv: False,} &\text{price: 27300,}\\ \text{s2 : } &\text{B_max: 27,} &\text{B_min: 0,} &\text{U_c: 2.5,} &\text{U_d: 2.5,} &\text{E_max: 0,} &\text{E_min: 0,} &\text{use_pv: True,} &\text{price: 35125,}\\ \text{s3 : } &\text{B_max: 0,} &\text{B_min: 0,} &\text{U_c: 1.9,} &\text{U_d: 1.9,} &\text{E_max: 60,} &\text{E_min: 24,} &\text{use_pv: False,} &\text{price: 4000,}\\ \text{s4 : } &\text{B_max: 0,} &\text{B_min: 0,} &\text{U_c: 1.9,} &\text{U_d: 1.9,} &\text{E_max: 60,} &\text{E_min: 24,} &\text{use_pv: True,} &\text{price: 17145,}\\ \text{s5 : } &\text{B_max: 10,} &\text{B_min: 0,} &\text{U_c: 1.9,} &\text{U_d: 1.9,} &\text{E_max: 60,} &\text{E_min: 24,} &\text{use_pv: True,} &\text{price: 23724,} \end{cases}
In [2]:
from model import *
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
scenarios = ["s0","s1","s2","s3","s4","s5"]
pd.options.display.max_columns = 500
pd.options.display.max_rows = 200
pd.options.display.float_format = '{:,.0f}'.format
import gurobipy as gp
from gurobipy import GRB
import pickle
import numpy_financial as npf
In [3]:
pro_results, pro_dres, pro_key_results, pro_npvs, pro_npvs2 = pro_ctrl(run=False,house_num=4)
gmp_results, gmp_dres, gmp_key_results, gmp_npvs, gmp_npvs2= gmp_ctrl(run=False,house_num=4)
In [4]:
fig = px.line(pro_dres[(pro_dres.Rate=='Time-of-Use') & (pro_dres.Sell==True) & (pro_dres.Scenario=='s1')], x='Time (Month-Day/Hour:Minute)', y=["P (GMP)","P (Flat)","P (ToU)", "P (ToU for EV)"], animation_frame= 'Scenario', title="Electricity price", labels={"value":"$", "P (GMP)": "P (RTLMP)"}, range_y=[0,0.3])
newnames = {'P (GMP)':'RTLMP', 'P (Flat)': 'Flat', 'P (ToU)': 'ToU', 'P (ToU for EV)': 'ToU for EV'}
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
                                      legendgroup = newnames[t.name],
                                      hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
                                     )
                  )
fig.show()
In [5]:
gmp_dres= gmp_dres.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & Flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
tmp = gmp_dres[gmp_dres.Scenario == 's3: EV']

# Create figure with secondary y-axis
fig = make_subplots(specs=[[{"secondary_y": True}]])

# Add traces
fig.add_trace(
    go.Scatter(x=tmp['Time (Month-Day/Hour:Minute)'], y=tmp["Flow from Grid"], name="Flow from Grid"),
    secondary_y=False,
)

fig.add_trace(
    go.Scatter(x=tmp['Time (Month-Day/Hour:Minute)'], y=tmp["P_GMP"], name="RTLMP"),
    secondary_y=True,
)

# fig.update_layout(
#     title_text="Double Y Axis Example"
# )

fig.update_xaxes(title_text="Time (Month-Day/Hour:Minute)")

# Set y-axes titles
fig.update_yaxes(title_text="<b>kWh</b> (flow)", secondary_y=False)
fig.update_yaxes(title_text="<b>$/kWh</b> (rate)", secondary_y=True)

fig.show()
In [6]:
print('The dirstributor controls')
for i in range(0,6):
    db = gmp_results[gmp_results.Scenario==f"s{i}"]
    fig = go.Figure(data=[go.Sankey(
            node = dict(
            pad = 15,
            thickness = 20,
            line = dict(color = "black", width = 0.5),
            label = ["Grid (G)", "Solar PV (R)", "ESS (B)", "Load (L)", "EV (E)"]
        ),
        link = dict(
          source = [0, 0, 1, 1, 1, 2, 2, 0, 1, 4, 4],
          target = [2, 3, 0, 2, 3, 0, 3, 4, 4, 0, 3],
          value  = [db.loc[:, "x^GB"].sum(), db.loc[:, "x^GL"].sum(), db.loc[:, "x^RG"].sum(), db.loc[:, "x^RB"].sum(), db.loc[:, "x^RL"].sum(), db.loc[:, "x^BG"].sum(), db.loc[:, "x^BL"].sum(), db.loc[:, "x^GE"].sum(), db.loc[:, "x^RE"].sum(), db.loc[:, "x^EG"].sum(), db.loc[:, "x^EL"].sum()]
      ))])

    fig.update_layout(title_text=f"Scenario {i}", font_size=10)
    fig.show()
The dirstributor controls
In [7]:
pro_dres = pro_dres.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & Flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
fig = px.line(pro_dres[(pro_dres.Rate=='TOU') & (pro_dres.Sell==True)], x='Time (Month-Day/Hour:Minute)', y="Flow from Grid", color= 'Scenario', title="Flow from Grid when system is controlled by the prosumer (in 15-minutes time-steps), rate is TOU", labels={"Flow from Grid":"kWh"}, range_y=[-8,8])
fig.show()
In [15]:
print('The prosumer controls (Scenarios)')
pro_results = pro_results.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
tmp = pro_results[pro_results.Rate == "TOU"]
Scen = ['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery']
for i in range(0,6):
    db = tmp[tmp.Scenario==Scen[i]]
    fig = go.Figure(data=[go.Sankey(
            node = dict(
            pad = 15,
            thickness = 20,
            line = dict(color = "black", width = 0.5),
            label = ["Grid (G)", "Solar PV (R)", "ESS (B)", "Load (L)", "EV (E)"]
        ),
        link = dict(
          source = [0, 0, 1, 1, 1, 2, 2, 0, 1, 4, 4],
          target = [2, 3, 0, 2, 3, 0, 3, 4, 4, 0, 3],
          value  = [db.loc[:, "x^GB"].sum(), db.loc[:, "x^GL"].sum(), db.loc[:, "x^RG"].sum(), db.loc[:, "x^RB"].sum(), db.loc[:, "x^RL"].sum(), db.loc[:, "x^BG"].sum(), db.loc[:, "x^BL"].sum(), db.loc[:, "x^GE"].sum(), db.loc[:, "x^RE"].sum(), db.loc[:, "x^EG"].sum(), db.loc[:, "x^EL"].sum()]
      ))])

    fig.update_layout(title_text=f"Scenario {Scen[i]}", font_size=10)
    fig.show()
The prosumer controls (Scenarios)
In [9]:
pro_key_results = pro_key_results.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
fig = px.bar(pro_key_results[pro_key_results.Sell == True], x='Rate', y="npv (%6.19)", color = 'Scenario', barmode='group', title="NPV of scenarios where prosumer controls",range_y=[-35000,15000])
fig.show()
In [10]:
fig = px.bar(pro_key_results[pro_key_results.Sell == True], x='Rate', y="GMP's cost", color = 'Scenario', barmode='group', title="GMP's cost when system is controlled by PRO",range_y=[0,6000],labels={"GMP's cost":"System cost ($)","Sell":"Selling rate"})
fig.show()
In [11]:
pro_results = pro_results.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
tmp = pro_results[pro_results.Sell==True]
fig = px.line(tmp[tmp.Rate == 'TOU'], x='Month', y="Peak load", color = "Scenario", range_y = [0,30], title="Peak loads when system is controlled by (Rate: TOU)", labels={"Peak load":"kW"})
fig.show()
fig = px.line(tmp[tmp.Rate == 'TOU EV & Flat'], x='Month', y="Peak load", color = "Scenario", range_y = [0,30], title="Peak loads when system is controlled by (Rate: TOU EV & Flat)", labels={"Peak load":"kW"})
fig.show()
In [12]:
print('The prosumer controls (Rates)')
tmp = pro_results[pro_results.Scenario == "s3: EV"]
Rates = ['Flat', 'TOU', 'TOU EV & Flat', 'RTLMP', 'TOU&RTLMP']
for i in range(0,5):
    db = tmp[tmp.Rate==Rates[i]]
    fig = go.Figure(data=[go.Sankey(
            node = dict(
            pad = 15,
            thickness = 20,
            line = dict(color = "black", width = 0.5),
            label = ["Grid (G)", "Solar PV (R)", "ESS (B)", "Load (L)", "EV (E)"]
        ),
        link = dict(
          source = [0, 0, 1, 1, 1, 2, 2, 0, 1, 4, 4],
          target = [2, 3, 0, 2, 3, 0, 3, 4, 4, 0, 3],
          value  = [db.loc[:, "x^GB"].sum(), db.loc[:, "x^GL"].sum(), db.loc[:, "x^RG"].sum(), db.loc[:, "x^RB"].sum(), db.loc[:, "x^RL"].sum(), db.loc[:, "x^BG"].sum(), db.loc[:, "x^BL"].sum(), db.loc[:, "x^GE"].sum(), db.loc[:, "x^RE"].sum(), db.loc[:, "x^EG"].sum(), db.loc[:, "x^EL"].sum()]
      ))])

    fig.update_layout(title_text=f"Rate:  {Rates[i]}", font_size=10)
    fig.show()
The prosumer controls (Rates)
In [13]:
gmpp = gmp_key_results.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
gmppp = gmpp.drop(["Pro's cost (buy : flat & sell : flat)", "Pro's cost (buy : Time-of-Use EV & sell : Time-of-Use)", "Pro's cost (buy : Time-of-Use EV & sell : flat)", "Pro's cost (buy : Time-of-Use & sell : Time-of-Use)", "Pro's cost (buy : flat & sell : Time-of-Use)", "Pro's cost (buy : Time-of-Use & sell : flat)"], axis=1)
gmpppp = gmppp.drop(["B_max","B_min","U_c","U_d","E_max","E_min","use_pv","price","Agent","Trade","Rate"], axis=1)
gmpppp['Net trade'] = gmpppp["GMP's cost"] - gmpppp["System cost"]
gmpppp['Maximum peak load'] = gmp_results.groupby("Scenario").max()["Peak load"]
gmpppp = gmpppp.rename(columns={"GMP's cost": 'Total cost', "internal rate of return (%)" : "IRR", "saving" : "Saving", "npv (%6.19)": "NPV"})
# gmpppp["Total flow from grid"] = gmp_results.groupby("Scenario").sum()["Flow from Grid"]
tmp = gmp_results.groupby("Scenario").sum()
gmpppp["Total flow taken from grid"] = tmp["x^GL"] + tmp["x^GB"] + tmp["x^GE"]
gmpppp["Total flow sent to grid"] = tmp["x^RG"] + tmp["x^BG * eta_d"] + tmp["x^EG * eta_d"]
temp = ['Scenario', 'Net trade','System cost', 'Total cost', 'Saving','NPV','IRR', 'Maximum peak load', "Total flow taken from grid", "Total flow sent to grid"]
gmpppp = gmpppp[temp]
gmpppp
Out[13]:
Scenario Net trade System cost Total cost Saving NPV IRR Maximum peak load Total flow taken from grid Total flow sent to grid
s0 s0: Status Quo 484 2,050 2,534 0 0 NaN 13 14,110 0
s1 s1: Battery 348 497 845 1,689 -11,094 -1 4 19,997 5,068
s2 s2: Battery+PV 31 627 657 1,877 -17,121 -3 5 17,023 12,610
s3 s3: EV 249 1,773 2,022 512 909 10 12 27,510 9,224
s4 s4: EV+PV -14 1,485 1,470 1,064 -6,938 -1 10 22,546 15,205
s5 s5: EV+PV+Battery 17 711 728 1,806 -6,398 2 6 18,920 11,798
In [14]:
pro1 = pro_key_results.replace(['s0','s1','s2','s3','s4','s5','Time-of-Use', "Time-of-Use EV & flat", "flat"],['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery', "TOU", "TOU EV & Flat", "Flat"])
proo = pro1.drop(["B_max","B_min","U_c","U_d","E_max","E_min","use_pv","price","Agent"], axis=1)
tmp = ['Rate','Sell','Scenario',"Pro's cost","GMP's cost",'saving','npv (%6.19)','internal rate of return (%)']
proo = proo[tmp]
proo.reset_index(drop=True, inplace=True)
pro_results["Total flow taken from grid"] = pro_results["x^GL"] + pro_results["x^GE"] + pro_results["x^GB"]
pro_results["Total flow sent to grid"] = pro_results["x^RG"] + pro_results["x^BG * eta_d"] + pro_results["x^EG * eta_d"]
for s in ['s0: Status Quo', 's1: Battery', 's2: Battery+PV', 's3: EV', 's4: EV+PV', 's5: EV+PV+Battery']:
    for p in ['Flat', 'TOU', 'TOU EV & Flat', 'RTLMP', 'TOU&RTLMP']:
        for t in [True, False]:
            proo.loc[(proo.Sell == t) & (proo.Scenario == s) & (proo.Rate == p), "Total flow sent to grid"] = pro_results.groupby(['Rate','Sell','Scenario']).sum().query(f'Rate == "{p}" and Sell == {t} and Scenario == "{s}"')["Total flow sent to grid"].to_numpy()[0]
            proo.loc[(proo.Sell == t) & (proo.Scenario == s) & (proo.Rate == p), "Total flow taken from grid"] = pro_results.groupby(['Rate','Sell','Scenario']).sum().query(f'Rate == "{p}" and Sell == {t} and Scenario == "{s}"')["Total flow taken from grid"].to_numpy()[0]
            proo.loc[(proo.Sell == t) & (proo.Scenario == s) & (proo.Rate == p), "Maximum peak load"] = pro_results.groupby(['Rate','Sell','Scenario']).max().query(f'Rate == "{p}" and Sell == {t} and Scenario == "{s}"')["Peak load"].to_numpy()[0]
proo = proo[['Rate', 'Sell', 'Scenario', "Pro's cost", "GMP's cost", 'saving', 'npv (%6.19)', 'internal rate of return (%)', 'Maximum peak load', "Total flow taken from grid", "Total flow sent to grid"]]
# proo.reset_index(drop=True, inplace=True)
pr = proo.query("Sell == True").drop(columns="Sell")
pro_2 = proo.query("Sell == False").drop(columns="Sell")
pr["NPV'"] = pro_2["npv (%6.19)"].values
pr["System Cost'"] = pro_2["GMP's cost"].values
pr.rename({"Pro's cost": 'Total Cost', "GMP's cost": 'System Cost', "saving": "Saving", "npv (%6.19)": "NPV", "internal rate of return (%)": "IRR"}, axis=1, inplace=True)
pr.reset_index(drop=True, inplace=True)
pr.set_index('Rate', inplace=True)
pr
Out[14]:
Scenario Total Cost System Cost Saving NPV IRR Maximum peak load Total flow taken from grid Total flow sent to grid NPV' System Cost'
Rate
Flat s0: Status Quo 2,558 2,050 0 0 NaN 13 14,110 0 0 2,050
Flat s1: Battery 2,551 2,050 6 -27,238 -39 13 14,071 0 -27,238 2,050
Flat s2: Battery+PV 709 2,013 1,849 -17,387 -3 13 10,193 7,051 -22,562 1,684
Flat s3: EV 2,551 2,928 7 -3,936 -29 19 16,953 2 -3,938 3,081
Flat s4: EV+PV 706 2,705 1,851 616 7 20 11,468 5,459 -7,719 2,766
Flat s5: EV+PV+Battery 705 2,638 1,853 -5,948 2 17 11,458 5,459 -11,333 2,432
TOU s0: Status Quo 2,363 2,050 0 0 NaN 13 14,110 0 0 2,050
TOU s1: Battery 945 4,539 1,418 -13,697 -3 27 21,818 6,670 -22,736 4,236
TOU s2: Battery+PV -293 3,091 2,657 -9,640 2 22 11,658 7,798 -21,847 2,360
TOU s3: EV 1,249 3,131 1,115 6,693 27 19 22,237 4,606 451 3,039
TOU s4: EV+PV -462 2,976 2,826 9,964 14 18 16,805 10,117 -4,959 2,831
TOU s5: EV+PV+Battery -813 3,050 3,176 6,744 10 19 17,143 10,198 -8,549 2,423
TOU EV & Flat s0: Status Quo 2,558 2,050 0 0 NaN 13 14,110 0 0 2,050
TOU EV & Flat s1: Battery 2,551 2,050 6 -27,238 -39 13 14,071 0 -27,238 2,050
TOU EV & Flat s2: Battery+PV 709 2,013 1,849 -17,387 -3 13 10,193 7,051 -22,562 1,684
TOU EV & Flat s3: EV 1,499 2,084 1,059 6,161 26 13 45,893 25,106 -204 2,040
TOU EV & Flat s4: EV+PV -346 2,017 2,904 10,713 15 13 43,632 33,788 -5,090 2,010
TOU EV & Flat s5: EV+PV+Battery -348 2,015 2,906 4,149 9 13 43,623 33,788 -9,005 1,877
RTLMP s0: Status Quo 484 2,050 0 0 NaN 13 14,110 0 0 2,050
RTLMP s1: Battery 37 4,542 447 -23,012 -14 27 41,446 24,331 -25,695 4,343
RTLMP s2: Battery+PV -86 3,483 570 -29,659 -14 20 25,908 20,663 -32,246 3,243
RTLMP s3: EV 241 3,099 244 -1,663 -1 18 27,906 9,566 -2,692 3,043
RTLMP s4: EV+PV -31 3,056 515 -12,200 -9 18 23,628 16,162 -14,584 2,907
RTLMP s5: EV+PV+Battery -91 3,035 575 -18,208 -11 18 26,465 18,567 -20,615 2,912
TOU&RTLMP s0: Status Quo 2,363 2,050 0 0 NaN 13 14,110 0 0 2,050
TOU&RTLMP s1: Battery 1,876 4,404 487 -22,628 -13 25 14,962 483 -22,736 4,236
TOU&RTLMP s2: Battery+PV 888 2,391 1,475 -20,973 -5 20 6,763 2,975 -21,847 2,360
TOU&RTLMP s3: EV 1,895 3,047 468 494 8 18 17,339 186 451 3,039
TOU&RTLMP s4: EV+PV 966 2,863 1,397 -3,741 3 18 11,544 5,297 -4,959 2,831
TOU&RTLMP s5: EV+PV+Battery 699 2,859 1,665 -7,755 1 18 9,748 3,339 -8,549 2,423